package io.yuncheng.modules.sys.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.yuncheng.common.config.DictConfig;
import io.yuncheng.common.utils.*;
import io.yuncheng.modules.sys.dao.SubAppLogCollectDao;
import io.yuncheng.modules.sys.entity.*;
import io.yuncheng.modules.sys.service.SubAppAssessmentSplitService;
import io.yuncheng.modules.sys.service.SubAppLogCollectService;
import io.yuncheng.common.utils.DateUtils;
import io.yuncheng.common.utils.Query;
import io.yuncheng.modules.sys.entity.*;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Service("subAppLogCollectService")
public class SubAppLogCollectServiceImpl extends ServiceImpl<SubAppLogCollectDao, SubAppLogCollectEntity> implements SubAppLogCollectService {
    private final Integer USER = 2;
    private final Integer NUM = 3;
    @Resource
    private SubAppAssessmentSplitService splitService;
    @Resource
    private DictConfig dictConfig;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SubAppLogCollectEntity> page = this.page(
                new Query<SubAppLogCollectEntity>().getPage(params),
                new QueryWrapper<SubAppLogCollectEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void saveOrUpdateByAppIdLogDate(SubAppLogCollectEntity entity) {
        QueryWrapper<SubAppLogCollectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_id", entity.getAppId()).eq("log_date", entity.getLogDate());
        SubAppLogCollectEntity one = getOne(queryWrapper);
        if (one != null) {
            entity.setId(one.getId());
            updateById(entity);
            return;
        }
        save(entity);
    }

    @Override
    public List<SubAppLogCollectEntity> queryListByAppId(Long AppId) {
        QueryWrapper<SubAppLogCollectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_id", AppId);
        return list(queryWrapper);
    }

    @Override
    public SubAppLogCollectObjectVo queryTotalByEntity(List<SubApplicationEntity> entity) {
        //通过密评的应用数量 通过密评在用的应用数量 商密登陆的用户数量 加密传输的终端数量  应用调用密码的总次数
        //当年通过密评的应用
        //当年通过密评在用的应用数量
        //当年应用调用的总次数
        //当年调用的密码构成
        String detail = "历年";
        SubAppLogCollectVo voUserTotal = SubAppLogCollectVo.initBuildInterface("商密登陆的用户数量",detail);
        SubAppLogCollectVo voNumTotal = SubAppLogCollectVo.initBuildInterface("加密传输的终端数量",detail);
        SubAppLogCollectVo voAppNumTotal = SubAppLogCollectVo.initBuildInterface("通过密评的应用数量",detail);
        SubAppLogCollectVo voCallTotal = SubAppLogCollectVo.initBuildInterface("应用调用密码算法的总次数",detail);
        SubAppLogCollectVo voCallRatioTotal = SubAppLogCollectVo.initBuildInterface("应用调用密码的占比",null );
        SubAppLogCollectVo inUseNum = SubAppLogCollectVo.initBuildInterface("通过密评在用的应用数量",detail);
        Date dateFirstYear = io.yuncheng.common.utils.DateUtils.getYearFirstDate(new Date());

        SubAppLogCollectVo appNumTotalCurrent = SubAppLogCollectVo.initBuildInterface("当年通过密评的应用数量",null);
        SubAppLogCollectVo inUseNumCurrent = SubAppLogCollectVo.initBuildInterface("当年通过密评在用的应用数量",null);
        SubAppLogCollectVo callTotalCurrent = SubAppLogCollectVo.initBuildInterface("当年密码调用的总次数",null);
        SubAppLogCollectVo callMonthTotalCurrent = SubAppLogCollectVo.initBuildInterface("省级单位当年密码使用情况","");
        SubAppLogCollectVo ratioTotalCurrent = SubAppLogCollectVo.initBuildInterface("当年密码算法调用构成",null);

        //todo 按照app和日期分组
        for (SubApplicationEntity applicationEntity : entity) {
            //全部密评
            List<SubAppAssessmentSplitEntity> list = splitService.queryNormalListByEntityNum(applicationEntity.getAppId());
            //按年分组
            Map<Date, List<SubAppAssessmentSplitEntity>> collect = list.stream().collect(Collectors.groupingBy(SubAppAssessmentSplitEntity::getAssessmentDate));
            SubAppLogCollectVo voUser = SubAppLogCollectVo.initBuildInterface(null);
            SubAppLogCollectVo voNum = SubAppLogCollectVo.initBuildInterface(null);
            SubAppLogCollectVo voAppNum = SubAppLogCollectVo.initBuildInterface(null);
            SubAppLogCollectVo voCurrentAppNum = SubAppLogCollectVo.initBuildInterface(null);

            collect.forEach((k, v) -> {
                if (!ObjectUtils.isEmpty(v)) {
                    Map<Integer, Integer> num = v.stream().filter(a -> a.getSplitTypeThree().equals(USER) || a.getSplitTypeThree().equals(NUM)).collect(Collectors.groupingBy(SubAppAssessmentSplitEntity::getSplitTypeThree, Collectors.summingInt(SubAppAssessmentSplitEntity::buildNum)));
                    voUser.putData(k, num.get(USER));
                    voNum.putData(k, num.get(NUM));
                    voAppNum.putData(k, 1);
                    if(io.yuncheng.common.utils.DateUtils.getYearFirstDate(k).compareTo(dateFirstYear) == 0){
                        voCurrentAppNum.putData(dateFirstYear,1);
                    }
                }
            });
            voNumTotal.add(voNum);
            voUserTotal.add(voUser);
            voAppNumTotal.add(voAppNum);
            appNumTotalCurrent.add(voCurrentAppNum);
            //调用密码次数
            List<SubAppLogCollectEntity> subAppLogCollectEntities = queryListByAppId(applicationEntity.getAppId());
            Map<Date, List<SubAppLogCollectEntity>> currentYear = subAppLogCollectEntities.stream().filter(a->dateFirstYear.compareTo(io.yuncheng.common.utils.DateUtils.getYearFirstDate(a.getLogDate()))==0).collect(Collectors.groupingBy(SubAppLogCollectEntity::buildByMonth));
            currentYear.forEach((k,v)->{
                if(!ObjectUtils.isEmpty(v)){
                    v.forEach(a->{
                        List<AgentArithmeticStepCollectEntity> stepEntities = JSON.parseObject(a.getStepArithTime(), new TypeReference<List<AgentArithmeticStepCollectEntity>>() {});
                        stepEntities.forEach(b->{
                            SubAppLogCollectVo arithTime = SubAppLogCollectVo.initBuildInterface(null);
                            arithTime.putData(k, b.getAlgoCount().intValue());
                            callMonthTotalCurrent.add(arithTime);
                        });
                    });
                }
            });

            Map<Date, List<SubAppLogCollectEntity>> time = subAppLogCollectEntities.stream().collect(Collectors.groupingBy(SubAppLogCollectEntity::buildByYear));

            time.forEach((k, v) -> {
                if (!ObjectUtils.isEmpty(v)) {
                    v.forEach(a -> {
                        List<AgentArithmeticStepCollectEntity> stepEntities = JSON.parseObject(a.getStepArithTime(), new TypeReference<List<AgentArithmeticStepCollectEntity>>() {
                        });
                        stepEntities.forEach(b -> {
                            SubAppLogCollectVo arithTime = SubAppLogCollectVo.initBuildInterface(null);
                            arithTime.putData(k, b.getAlgoCount().intValue());
                            voCallTotal.add(arithTime);
                            callTotalCurrent.add(arithTime);
                            SubAppLogCollectVo arithTime2 = SubAppLogCollectVo.initBuildInterface(null);
                            arithTime2.putMapData(k, b.getStepAlgo(), b.getAlgoCount().intValue());
                            voCallRatioTotal.add(arithTime2);
                            ratioTotalCurrent.add(arithTime2);
                        });
                    });
                    SubAppLogCollectVo inUse = SubAppLogCollectVo.initBuildInterface(null);
                    SubAppLogCollectVo inUseCurrent = SubAppLogCollectVo.initBuildInterface(null);
                    Integer inUseInteger = 0;
                    for (Date date : collect.keySet()) {
                        if (date.compareTo(k) == 0) {
                            if (!ObjectUtils.isEmpty(collect.get(date))) {
                                inUseInteger = 1;
                            }
                        }
                    }
                    if(DateUtils.getYearFirstDate(k).compareTo(dateFirstYear) == 0){
                        inUseCurrent.putData(dateFirstYear,1);
                    }
                    inUse.putData(k, inUseInteger);
                    inUseNum.add(inUse);
                    inUseNumCurrent.add(inUseCurrent);
                }
            });
        }
        SubAppLogCollectObjectVo vo = new SubAppLogCollectObjectVo();
        vo.setEncryptionNum(voNumTotal);
        vo.setLoginUser(voUserTotal);
        vo.setInUseNum(inUseNum);
        vo.setCallTotal(voCallTotal);
        vo.setAppNum(voAppNumTotal);

        vo.setCallCurrent(callTotalCurrent);
        vo.setAppNumCurrent(appNumTotalCurrent);
        vo.setInUseNumCurrent(inUseNumCurrent);
        vo.setRatioTotalCurrent(ratioTotalCurrent);

        vo.setCallMonthCurrent(callMonthTotalCurrent);
        return vo;

    }

    @Override
    public List<SubAppLogCollectVo> queryByAppId(Long appId) {
        SubAppLogCollectVo callMonthTotalCurrent = SubAppLogCollectVo.initBuildInterface("密码调用数量",null);
        SubAppLogCollectVo callTotalCurrent = SubAppLogCollectVo.initBuildInterface("算法调用占比以及趋势",null);
        SubAppLogCollectVo callTime = SubAppLogCollectVo.initBuildInterface("算法耗时",null);
        List<SubAppLogCollectEntity> subAppLogCollectEntities = queryListByAppId(appId);

        Map<Date, List<SubAppLogCollectEntity>> time = subAppLogCollectEntities.stream().collect(Collectors.groupingBy(SubAppLogCollectEntity::buildByMonth));
        time.forEach((k, v) -> {
            if (!ObjectUtils.isEmpty(v)) {
                v.forEach(a -> {
                    List<AgentArithmeticStepCollectEntity> stepEntities = JSON.parseObject(a.getStepArithTime(), new TypeReference<List<AgentArithmeticStepCollectEntity>>() {});
                    stepEntities.forEach(b -> {
                        SubAppLogCollectVo arithTime = SubAppLogCollectVo.initBuildInterface(null);
                        arithTime.putData(k, b.getAlgoCount().intValue());
                        callMonthTotalCurrent.add(arithTime);
                        SubAppLogCollectVo arithTime2 = SubAppLogCollectVo.initBuildInterface("算法调用占比以及趋势");
                        arithTime2.putMapData(k, b.getStepAlgo(), b.getAlgoCount().intValue());
                        callTotalCurrent.add(arithTime2);
                        SubAppLogCollectVo arithTime3 = SubAppLogCollectVo.initBuildInterface("算法耗时");
                        arithTime3.putMapData(k, b.getStepAlgo(), b.getTimeSpan().intValue());
                        callTime.add(arithTime3);
                    });
                });
            }
        });
        List<SubAppLogCollectVo> subAppLogCollectVo = callTotalCurrent.changeListDateKeyToStrKey();
        subAppLogCollectVo.add(callMonthTotalCurrent.buildMapForList());
        subAppLogCollectVo.addAll(callTime.changeListDateKeyToStrKey());
        return subAppLogCollectVo;
    }
}
